package com.ruoyi.web.controller.wxpay;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.domain.server.Mem;
import com.ruoyi.system.domain.Member;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.MemberService;
import com.ruoyi.web.config.WxPayConfig;
import com.ruoyi.web.mapper.OrderInfoMapper;
import com.ruoyi.web.pojo.OrderInfo;
import com.ruoyi.web.pojo.TransferInfo;
import com.ruoyi.web.pojo.TransferResponse;
import com.ruoyi.web.pojo.WechatTransferBatchesParam;
import com.ruoyi.web.service.WeChatOpenIdService;
import com.ruoyi.web.service.WeChatPayService;
import com.ruoyi.web.uniEnum.OrderInfoEnum;
import com.ruoyi.web.util.OrderNoUtils;
import com.ruoyi.web.vo.WXPayOrderReqVO;
import com.ruoyi.web.vo.WxPayRespVO;
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import com.wechat.pay.java.core.notification.RequestParam;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;
/*
 *  @author 雨安
 *  类名： WxPayController
 *  创建时间：2025/2/18
 */
@RestController
@RequestMapping("/wx/pay")
@Slf4j
public class WxPayController {
    // 微信 appId
    private static final String APP_ID = "wxbd664677f8367061";
    // 微信 AppSecret
    private static final String APP_SECRET = "b498ec52efbacda9913b7e717371a7fc";

    //pay
    @Resource
    private WeChatPayService weChatPayService;

    //订单
    @Resource
    private OrderInfoMapper orderInfoMapper;


    //会员
    @Resource
    private MemberService memberService;

    /**
     * 会员充值
     */
    @PostMapping("/recharge/member")
    public AjaxResult rechargeMember(String code,Long memberId) throws Exception {
        //查询会员对象
        Member member = memberService.getById(memberId);
        System.out.println(memberId + "ssssssssswwwwwwwwwwwwwwwwwwwwwwaaaaaaaaaaaaaa" + code);
        //判断member不为 null
        if (Objects.isNull(member)){
            //返回结果
            return AjaxResult.error("当前开通的会员异常。");
        }
        //判断会员价格
        if (Objects.isNull(member.getPrice())){
            //返回结果
            return AjaxResult.error("当前开通的会员价格异常,请联系管理员。");
        }
        //获取openid
        String openId = getOpenId(code);
        //获取订单号
        String orderNo = OrderNoUtils.getOrderNo();
        System.out.println(openId + "获取到了openId" + member);
        //创建请求对象
        WXPayOrderReqVO wxPayOrderReqVO = new WXPayOrderReqVO();
        //设置类型
        wxPayOrderReqVO.setOrderType("会员充值");
        //* 100因为微信的钱已分为单位
        wxPayOrderReqVO.setTotalPrice(member.getPrice().multiply(BigDecimal.valueOf(100)));
        //设置商品名
        wxPayOrderReqVO.setGoodsName("会员");
        //设置用户openid
        wxPayOrderReqVO.setOpenId(openId);
        //设置订单号
        wxPayOrderReqVO.setOrderSn(orderNo);
        //调用预定支付订单
        WxPayRespVO order = weChatPayService.createMemberOrder(wxPayOrderReqVO);
        System.out.println(order + "我是查看微信下单回调");
        //返回前存储微信订单信息
        OrderInfo orderInfo = new OrderInfo();
        //设置订单号
        orderInfo.setOrderNo(orderNo);
        //设置实付金额
        orderInfo.setFund(member.getPrice().negate());
        //设置用户编号
        orderInfo.setUserId(SecurityUtils.getUserId());
        //设置订单备注
        orderInfo.setDescription("会员充值");
        //设置订单状态
        orderInfo.setOrderType(OrderInfoEnum.DaiZhiFu.getType());
        //设置会员编号
        orderInfo.setMemberId(memberId);
        //设置默认值
        orderInfo.setCreateTime(new Date());
        orderInfo.setCreateBy(SecurityUtils.getUsername());
        orderInfo.setUpdateTime(new Date());
        orderInfo.setUpdateBy(SecurityUtils.getUsername());
        orderInfo.setDeleteFlag(Boolean.FALSE);
        //执行添加
        orderInfoMapper.insert(orderInfo);
        //设置返回前端的订单号
        order.setOrderNo(orderNo);
        //返回最终结果
        return AjaxResult.success(order);
    }

    /**
     * 通过code获取open id 充值积分
     * @return 返回操作结果
     */
    @PostMapping("/get/openid")
    public AjaxResult getOpenId(String code,String recharge,HttpServletRequest httpRequest) throws Exception {
        if (recharge == null || recharge.equals("0")){
            return AjaxResult.error("请选择充值金额");
        }
        String orderNo = OrderNoUtils.getOrderNo();
        //获取openid
        String openId = getOpenId(code);
        //创建请求对象
        WXPayOrderReqVO wxPayOrderReqVO = new WXPayOrderReqVO();
        //设置类型
        wxPayOrderReqVO.setOrderType("积分充值");
        //* 100因为微信的钱已分为单位  此处再*0.98是因为需要减少百分之2的手续费
        wxPayOrderReqVO.setTotalPrice(BigDecimal.valueOf(Integer.parseInt(recharge)).multiply(BigDecimal.valueOf(100)));
        //设置商品名
        wxPayOrderReqVO.setGoodsName("积分");
        //设置用户openid
        wxPayOrderReqVO.setOpenId(openId);
        //设置订单号
        wxPayOrderReqVO.setOrderSn(orderNo);
        //调用预定支付订单
        WxPayRespVO order = weChatPayService.createOrder(wxPayOrderReqVO);
        System.out.println(order + "我是查看微信下单回调");
        //返回前存储微信订单信息
        OrderInfo orderInfo = new OrderInfo();
        //设置订单号
        orderInfo.setOrderNo(orderNo);
        //设置实付金额
        orderInfo.setFund(BigDecimal.valueOf(Integer.valueOf(recharge)));
        //设置用户编号
        orderInfo.setUserId(SecurityUtils.getUserId());
        //设置订单备注
        orderInfo.setDescription("积分充值");
        //设置订单状态
        orderInfo.setOrderType(OrderInfoEnum.DaiZhiFu.getType());
        //设置默认值
        orderInfo.setCreateTime(new Date());
        orderInfo.setCreateBy(SecurityUtils.getUsername());
        orderInfo.setUpdateTime(new Date());
        orderInfo.setUpdateBy(SecurityUtils.getUsername());
        orderInfo.setDeleteFlag(Boolean.FALSE);
        //执行添加
        orderInfoMapper.insert(orderInfo);
        //设置返回前端的订单号
        order.setOrderNo(orderNo);
        //返回结果
        return AjaxResult.success(order);
    }



    //配置
    @Resource
    private WxPayConfig wxPayConfig;

    //用户
    @Resource
    private SysUserMapper sysUserMapper;

    // API接口地址
    private static final String API_URL = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";

    //用户提现功能
    @PostMapping("/user/withdrawal")
    public AjaxResult userWithdrawal(String code,String withdrawal) throws Exception {
        //查询用户可提现金额是否
        SysUser sysUser = sysUserMapper.selectUserById(SecurityUtils.getUserId());
        //判断user不为 null
        if (Objects.nonNull(sysUser) && sysUser.getIncome().compareTo(BigDecimal.valueOf(Long.valueOf(withdrawal))) >= 0){
            //获取openid
            String openId = getOpenId(code);
            //订单号
            String orderNo = OrderNoUtils.getNo();
            //定义请求体
            WechatTransferBatchesParam wechatTransferBatchesParam = new WechatTransferBatchesParam();
            //设置appid
            wechatTransferBatchesParam.setAppid(wxPayConfig.getAppid());
            //设置唯一订单
            wechatTransferBatchesParam.setOut_bill_no(orderNo);
            //设置审批号
            wechatTransferBatchesParam.setTransfer_scene_id("1005");
            //设置openid
            wechatTransferBatchesParam.setOpenid(openId);
            // 将字符串转换为 BigDecimal
            BigDecimal withdrawalAmount = new BigDecimal(withdrawal);
            // 乘以 100
            BigDecimal transferAmount = withdrawalAmount.multiply(BigDecimal.valueOf(100))
                    // 乘以 0.98
                    .multiply(BigDecimal.valueOf(0.98));
            // 四舍五入并转换为整数  //设置转账金额
            wechatTransferBatchesParam.setTransfer_amount(transferAmount.setScale(0, RoundingMode.HALF_UP).intValue());
//            wechatTransferBatchesParam.setTransfer_amount(10);
            //设置转账备注
            wechatTransferBatchesParam.setTransfer_remark("创流客提现打款");
            //设置回调地址
            wechatTransferBatchesParam.setNotify_url(wxPayConfig.getNotifyDomain() + "/uni/pay/withdrawal/success");
            //创建list集合
            List<TransferInfo> list = new ArrayList<>();
            //设置内容
            TransferInfo transferInfo = new TransferInfo();
            transferInfo.setInfo_type("岗位类型");
            transferInfo.setInfo_content("用户");
            list.add(transferInfo);
            TransferInfo transferInfo2 = new TransferInfo();
            transferInfo2.setInfo_type("报酬说明");
            transferInfo2.setInfo_content("积分提现");
            list.add(transferInfo2);
            wechatTransferBatchesParam.setTransfer_scene_report_infos(list);
            //创建订单对象
            OrderInfo orderInfo = new OrderInfo();
            //设置订单号
            orderInfo.setOrderNo(orderNo);
            //设置订单金额
            orderInfo.setFund(BigDecimal.valueOf(Integer.valueOf(withdrawal)).negate());
            //设置订单用户编号
            orderInfo.setUserId(SecurityUtils.getUserId());
            //设置订单备注
            orderInfo.setDescription("余额提现");
            //设置订单状态
            orderInfo.setOrderType(OrderInfoEnum.TiXianShenQing.getType());
            //设置默认值
            orderInfo.setCreateBy(SecurityUtils.getUsername());
            orderInfo.setCreateTime(new Date());
            orderInfo.setUpdateBy(SecurityUtils.getUsername());
            orderInfo.setUpdateTime(new Date());
            orderInfo.setDeleteFlag(Boolean.FALSE);
            //保存order
            orderInfoMapper.insert(orderInfo);
            //得到扣款后的值
            BigDecimal newIncome = sysUser.getIncome().subtract(BigDecimal.valueOf(Long.valueOf(withdrawal)));
            //用户调用提现之前需要先扣除账户的收益
            sysUser.setIncome(newIncome);
            //设置默认值
            sysUser.setUpdateBy(SecurityUtils.getUsername());
            sysUser.setUpdateTime(new Date());
            //执行修改扣款
            sysUserMapper.updateUser(sysUser);
            //获取微信官方的返回
            String s = sendPostRequest(wechatTransferBatchesParam);
            //创建gson对象
            Gson gson = new Gson();
            //转化对象
            TransferResponse response = gson.fromJson(s, TransferResponse.class);
            //返回结果
            return AjaxResult.success(response);
        }else{
            return AjaxResult.error("用户可提现收益不足。");
        }
    }

    public String sendPostRequest(WechatTransferBatchesParam wechatTransferBatchesParam) throws Exception {
        String url = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";
        //定义一个post请求对象
        HttpPost httpPost = new HttpPost(url);

        CloseableHttpClient wxPayClient = wxPayConfig.getWxPayClient(wxPayConfig.getVerifier());

        httpPost.setHeader("Content-Type", "application/json");
        // 可能还需要设置其他请求头，如Authorization，这里省略
        httpPost.setHeader("Accept", "application/json");

        // 将WechatTransferBatchesParam对象转换为JSON字符串
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(wechatTransferBatchesParam);

        System.out.println(jsonString + "传递的值");
        // 设置请求体
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
        httpPost.setEntity(entity);


        // 发送请求并获取响应
        try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200 || statusCode == 201) { // 根据API的响应码判断请求是否成功
                // 读取响应体
                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
                return responseBody; // 返回响应体内容
            } else {
                // 处理错误响应
                String errorMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                throw new RuntimeException("请求失败，状态码：" + statusCode + "，响应内容：" + errorMessage);
            }
        }
    }

    // 替换为用户获取的code
    public static String getOpenId(String code){
        //调用service
        WeChatOpenIdService service = new WeChatOpenIdService(APP_ID, APP_SECRET);
        try {
            //解密获取 openid
            String openId = service.getOpenId(code);
            //输出openid
            System.out.println("用户的 OpenID: " + openId);
            //返回openid
            return openId;
        } catch (Exception e) {
            //处理异常
            e.printStackTrace();
            //返回异常
            return e.getMessage();
        }
    }

    @GetMapping("/get/access/token")
    public AjaxResult getUniAccessToken() throws Exception {
        //返回结果
        return AjaxResult.success(getAccessToken());
    }

    //获取token
    public String getAccessToken() throws Exception {
        String urlString = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APP_ID + "&secret=" + APP_SECRET;
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        // 读取响应
        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String inputLine;
        StringBuilder response = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        // 打印返回的完整响应
        System.out.println("Response: " + response.toString());
        // 解析 JSON，提取 access_token
        JSONObject jsonResponse = new JSONObject(response.toString());
        String accessToken = jsonResponse.getString("access_token");
        // 返回 access_token
        return accessToken;
    }




}
